import { _decorator, Component, Node, director, Scene, AssetManager, assetManager, Prefab, SpriteFrame, Texture2D, Asset, log } from 'cc';
import { Panel, UIManager } from './UIManager';
import PrefsUtil from '../Utils/PrefsUtil';
import { Constant } from '../Datas/Constant';
import Banner from '../../Banner';
import { ZTool } from '../Utils/ZTool';

const { ccclass, property } = _decorator;

/*** 所有 Bundle 包的名字，名字需要和包名保持一致 */
export enum Bundles {
    Prefabs = "Prefabs",
    Prefab_LV = "Prefab_LV",
    Sprites = "Sprites",
    Model = "Model",
}

export enum RemoteBundles {
}

@ccclass('BundleManager')
export class BundleManager extends Component {
    private static _instance: any;
    public static get Instance(): BundleManager {
        if (BundleManager._instance == null) BundleManager._instance = new BundleManager();
        return BundleManager._instance;
    }

    /*** Key: Bundle 名字   Value: Bundle */
    static BundleMap: Map<string, AssetManager.Bundle> = new Map<string, AssetManager.Bundle>();
    static AssetMap: Map<string, Asset> = new Map<string, Asset>();

    static AgreePolicy: boolean = false;
    static LocalLoadDone: boolean = false;
    static RemoteLoadDone: boolean = false;
    static DataLoadDone: boolean = false;
    // static LoadDirDone: boolean = false;

    protected onLoad(): void {
        Banner.Instance.SetCityIsWhite();

        BundleManager.AgreePolicy = false;
        BundleManager.LocalLoadDone = false;
        BundleManager.RemoteLoadDone = false;
        BundleManager.DataLoadDone = false;
        // BundleManager.LoadDirDone = false;


        // DataManager.InitData(() => {
        BundleManager.DataLoadDone = true;
        //     this.SuccessCallback();
        // });

        // UIManager.ShowTip("正在加载资源...");
        this.LoadRemoteBundles(() => {
            BundleManager.RemoteLoadDone = true;
            this.SuccessCallback();
        });

        this.LoadBundles();

        if (PrefsUtil.GetBool(Constant.Key.AgreePolicy) || Banner.IS_ANDROID) { //如果是安卓或者用户之前同意过不加载隐私协议
            BundleManager.AgreePolicy = true;
            this.SuccessCallback();
        } else {
            UIManager.GetInstance().ShowPanel(Panel.PrivacyPanel, [true, () => { //加载隐私协议
                BundleManager.AgreePolicy = true;
                this.SuccessCallback();
            }]);
        }
    }

    SuccessCallback() {
        if (BundleManager.AgreePolicy && BundleManager.LocalLoadDone && BundleManager.RemoteLoadDone && BundleManager.DataLoadDone) {
            // BundleManager.LoadDirBundleAsset(Bundles.Sprites);
            this.scheduleOnce(() => { director.loadScene("Menu"); }, 1);
        }
    }

    LoadBundles() {
        const bundleNames = ZTool.GetEnumValues(Bundles);
        const bundlePromises = bundleNames.map(name => {
            return new Promise((resolve, reject) => {
                assetManager.loadBundle(name, (err, bundle) => {
                    if (err) {
                        reject([name, err]);
                    } else {
                        resolve(bundle);
                    }
                });
            });
        });

        Promise.all(bundlePromises)
            .then((bundles: AssetManager.Bundle[]) => {
                for (let i = 0; i < bundles.length; i++) {
                    if (!BundleManager.BundleMap.has(bundles[i].name) || BundleManager.BundleMap.get(bundles[i].name) != bundles[i]) {
                        BundleManager.BundleMap.set(bundles[i].name, bundles[i]);
                        console.log(`加载本地 Bundle: ${bundles[i].name} 成功`);
                    }
                }
                BundleManager.LocalLoadDone = true;
                this.SuccessCallback();
                // UIManager.ShowTip("加载资源成功");
            })
            .catch(error => {
                UIManager.ShowTip("加载资源失败");
                console.error(`加载本地 Bundle:${error[0]} 失败:[${error[1]}]`);
            });
    }

    //加载远程包无论成功失败都进入游戏
    LoadRemoteBundles(callback: Function = null) {
        const bundleNames = ZTool.GetEnumValues(RemoteBundles);
        const bundlePromises = bundleNames.map(name => {
            return new Promise((resolve, reject) => {
                assetManager.loadBundle(name, (err, bundle) => {
                    if (err) {
                        reject([name, err]);
                    } else {
                        resolve(bundle);
                    }
                });
            });
        });

        Promise.all(bundlePromises)
            .then((bundles: AssetManager.Bundle[]) => {
                for (let i = 0; i < bundles.length; i++) {
                    if (!BundleManager.BundleMap.has(bundles[i].name) || BundleManager.BundleMap.get(bundles[i].name) != bundles[i]) {
                        BundleManager.BundleMap.set(bundles[i].name, bundles[i]);
                        console.log(`加载远程 Bundle: ${bundles[i].name} 成功`);
                    }
                }
                callback && callback();
            })
            .catch(error => {
                callback && callback();
                UIManager.ShowTip("加载资源失败,请检查网络...");

                console.error(`加载远程 Bundle:${error[0]} 失败:[${error[1]}]`);
            });
    }

    /*** 设置 Bundle 包 */
    public static SetBundle(name: string, cb: Function = null) {
        assetManager.loadBundle(name, (err, bundle) => {
            if (err) {
                console.error(`加载 Bundle 包：${name} 失败。`);
                return;
            }
            BundleManager.BundleMap.set(name, bundle);
            cb && cb();
        });
    }

    /*** 获取 Bundle 包 */
    public static GetBundle(bundle: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        return this.BundleMap.get(bundle);
    }

    /*** 加载 Bundle 包内资源 */
    public static Load(bundle: string, path: string, type: any, cb: Function = () => { }) {
        if (this.CheckBundleIsNull(bundle)) return;
        this.BundleMap.get(bundle).load(path, type, (err: any, res: any) => {
            if (err) {
                console.error(err.message || err);
                cb(err, res);
                return;
            }

            cb && cb(null, res);
        })
    }

    /*** 加载 Bundle 包内场景 */
    public static LoadBundleScene(bundle: string, scene: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        this.BundleMap.get(bundle).loadScene(scene, Scene, (err, scene) => {
            if (err) {
                console.error(`加载 Bundle: ${bundle} 场景失败: ${scene}`);
                return;
            }

            director.runScene(scene);
        });
    }

    /*** 加载 Bundle 包内预制体 */
    public static LoadPrefab(bundle: string, path: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        return new Promise((resolve, reject) => {
            this.Load(bundle, `${path}`, Prefab, (err: any, prefab: Prefab) => {
                if (err) {
                    console.error(`加载 Bundle: ${bundle} cc.Prefab 加载失败 Path: ${path}`);
                    reject && reject();
                    return;
                }

                resolve && resolve(prefab);
            });
        });
    }

    /*** 加载 Bundle 包内 cc.SpriteFrame */
    public static LoadSpriteFrame(bundle: string, path: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        return new Promise((resolve, reject) => {
            this.Load(bundle, `${path}/spriteFrame`, SpriteFrame, (err: any, spriteFrame: SpriteFrame) => {
                if (err) {
                    console.error(`加载 Bundle: ${bundle} cc.SpriteFrame 加载失败 Path: ${path}`);
                    reject && reject();
                    return;
                }

                resolve && resolve(spriteFrame);
            });
        });
    }

    /*** 加载 Bundle 包内 cc.Texture2D */
    public static LoadTexture(bundle: string, path: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        return new Promise((resolve, reject) => {
            this.Load(bundle, `${path}/texture`, Texture2D, (err: any, texture: Texture2D) => {
                if (err) {
                    console.error(`加载 Bundle: ${bundle} cc.Texture2D 加载失败 Path: ${path}`);
                    reject && reject();
                    return;
                }

                resolve && resolve(texture);
            });
        });
    }

    /*** 检查 Bunle 包是否为空，可以特殊处理，请求用户连接网络重启游戏 */
    private static CheckBundleIsNull(bundle: string): boolean {
        if (!this.BundleMap.has(bundle)) {
            console.error(`不存在此 Bundle: ${bundle}，请检查 Bundle 名称或者网络`);
            return true;
        }
        return false;
    }

    //     bundle.loadDir(parseData.loadUrl, type, (error: Error, resource: T[]) => {
    //     if (error) {
    //         cc.error(`[Res.loadDir] load error: ${error}`);
    //         resolve([]);
    //     } else {
    //         let infos = bundle.getDirWithPath("", type);
    //         // let infos = bundle.getDirWithPath(url, type);
    //         resource.forEach((asset, i) => {
    //             let cachePath = parseData.bundle ? `ab:${parseData.bundle}/${infos[i].path}` : infos[i].path;
    //             this.cacheAsset(cachePath, asset, type, release);
    //         });
    //         resolve(resource);
    //     }
    // });

    // public static LoadDirBundleAsset(bundle: Bundles) {
    //     if (BundleManager.BundleMap.has(bundle)) {
    //         BundleManager.BundleMap.get(bundle).loadDir("/", (err: Error, assets: Asset[]) => {
    //             if (err) {
    //                 console.error(`bundle加载失败${err}`);
    //             } else {
    //                 assets.forEach(asset => {
    //                     if (asset.name !== "") {
    //                         BundleManager.AssetMap.set(asset.name, asset);
    //                     }
    //                 })
    //             }
    //         })
    //     }
    // }
}